package TenoriOn
{
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	public class WAVEncoder
	{	
		public static const SAMPLE_RATE_44100:int=44100;
		public static const SAMPLE_RATE_22050:int=22050;
		public static const BIT_DEPTH_16BIT:int=16;
		public static const BIT_DEPTH_8BIT:int=16;
		
		private var _sampleRate:int;
		private var _bitDepth:int;
		public var stereo:Boolean;
		
		public function WAVEncoder(stereo:Boolean=true,sampleRate:int=SAMPLE_RATE_44100,bitDepth:int=BIT_DEPTH_16BIT)
		{
			this.stereo=stereo;
			_sampleRate=sampleRate;
			_bitDepth=bitDepth;
		}
		
		public function get sampleRate():int{
			return _sampleRate;
		}
		public function set sampleRate(value:int):void{
			switch(value){
				case SAMPLE_RATE_22050:
					_sampleRate=22050;
					break;
				case SAMPLE_RATE_44100:
					_sampleRate=44100;
					break;
				default:
					throw new Error("TenoriOn.WAVEncoder Error: Invalid SampleRate");
			}
		}
		
		public function get bitDepth():int{
			return _bitDepth;
		}
		public function set bitDepth(value:int):void{
			switch(value){
				case BIT_DEPTH_16BIT:
					_bitDepth=16;
					break;
				case BIT_DEPTH_8BIT:
					_bitDepth=8;
					break;
				default:
					throw new Error("TenoriOn.WAVEncoder Error: Invalid Bit Depth");
			}
		}
		
		public function get blockAlign():int{
			return (stereo?2:1)*_bitDepth/8;
		}
		
		private var data:ByteArray;
		
		public function makeFile(file:File):void{
			var fmt:ByteArray=getFmt();
			var fileData:ByteArray=new ByteArray();
			fileData.endian=Endian.LITTLE_ENDIAN;
			fileData.writeMultiByte("RIFF","us-ascii");
			fileData.writeInt(fmt.length+data.length+4);
			fileData.writeMultiByte("WAVE","us-ascii");
			var fileObj:FileStream=new FileStream();
			fileObj.open(file,FileMode.WRITE);
			fileObj.writeBytes(fileData);
			fileObj.writeBytes(fmt);
			fileObj.writeBytes(data);
			fileObj.close();
		}
		
		private function getFmt():ByteArray{
			var fmt:ByteArray=new ByteArray();
			fmt.endian=Endian.LITTLE_ENDIAN;
			fmt.writeMultiByte("fmt ","us-ascii");
			fmt.writeInt(16);
			fmt.writeShort(1);
			fmt.writeShort((stereo?2:1));
			fmt.writeUnsignedInt(sampleRate);
			fmt.writeUnsignedInt(sampleRate*blockAlign);
			fmt.writeShort(blockAlign);
			fmt.writeShort(bitDepth);
			return fmt
		}
		public function writeData(samples:ByteArray):void{
			data=new ByteArray();
			data.endian=Endian.LITTLE_ENDIAN;
			data.writeMultiByte("data","us-ascii");
			data.writeUnsignedInt(samples.length);
			data.writeBytes(samples);
		}
	}
}